package com.trg.flex.frm
{
	import com.trg.flex.FlexUtils;
	import com.trg.flex.dt.DataTable;
	import com.trg.flex.frm.validation.InputValidationHelper;
	
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.FocusEvent;
	
	import mx.events.FlexEvent;

	[Event(name="validChanged", type="mx.events.PropertyChangeEvent")]
	public class FormSelectTable extends DataTable implements FormInput
	{
		public function FormSelectTable()
		{
			super();
			showSelectionColumn = true;
			preserveSelection = "off-screen";
			
			topContainer = this;
			topContainer.addEventListener(FlexEvent.ADD, addListener);
		}

		protected var formContainer:FormContainer;
		protected var topContainer:DisplayObject;

		protected function addListener(event:FlexEvent):void {
			topContainer.removeEventListener(FlexEvent.ADD, addListener);
			
			while(true) {
				if (topContainer.parent is FormContainer) {
					formContainer = topContainer.parent as FormContainer;
					formContainer.addElement(this);
					break;
				} else if (topContainer.parent == null) {
					topContainer.addEventListener(FlexEvent.ADD, addListener);
					break;
				}
				topContainer = topContainer.parent;
			}
		}
		
	//FormInput INTERFACE
		protected var _property:String;
	
		public function get property():String {
			return _property;
		}
		
		public function set property(property:String):void {
			_property = property;
		}
		
		public function set elementValue(value:Object):void {
			if (selectable == "multi") {
				if (value == null) {
					value = [];
				} else if (FlexUtils.isCollection(value)) {
					value = FlexUtils.collectionToArray(value);
				} else {
					value = [value];
				}
			}
			
			if (valueField != null && valueField.length > 0) {
				var o:Object;
				if (selectable == "multi") {
					var a:Array = [];
					for each (var item:* in value as Array) {
						o = {};
						FlexUtils.setNestedProperty(o, valueField, item, true);
						a.push(o);
					}
					selectedItems = a;
				} else {
					o = {};
					FlexUtils.setNestedProperty(o, valueField, value, true);
					selectedItem = o;
				}
			} else {
				if (selectable == "multi") {
					selectedItems = value as Array;
				} else {
					selectedItem = value;
				}
			}
		}
		
		public function get elementValue():Object {
			var expectedType:Class;
			if (valueField != null && valueField.length > 0) {
				if (selectable == "multi") {
					var items:Array = selectedItems;
					var a:Array = [];
					for each (var item:* in items) {
						a.push(FlexUtils.getNestedProperty(item, valueField));
					}
					return a;
					
					if (formContainer != null && _property != null) {
						expectedType = formContainer.getPropertyType(_property);
					} else {
						expectedType = Array;
					}
					
					if (expectedType is Array || expectedType == Object) {
						return a;
					}  else {
						return FlexUtils.arrayToCollection(a, expectedType);
					}
				} else {
					return FlexUtils.getNestedProperty(selectedItem, valueField);
				}					
			} else {
				if (selectable == "multi") {
					if (formContainer != null && _property != null) {
						expectedType = formContainer.getPropertyType(_property);
					} else {
						expectedType = Array;
					}
					
					if (expectedType is Array || expectedType == Object) {
						return selectedItems;
					}  else {
						return FlexUtils.arrayToCollection(selectedItems, expectedType);
					}
				} else {
					return selectedItem;
				}
			}
		}
		
		public function get validatorValue():* {
			if (selectable == "multi") {
				return selectedItems;
			} else {
				return selectedItem;
			}
		}

		
	//DataTable specific
		protected var _valueField:String;

		[Bindable]
		public function get valueField():String {
			return _valueField;
		}
		public function set valueField(value:String):void {
			_valueField = value;
			compareField = value;
		}
		
	//Validation
		protected var validationHelper:InputValidationHelper = new InputValidationHelper(this as FormInput, "validatorValue", Event.CHANGE, FocusEvent.FOCUS_OUT);
		
		[Bindable("validChanged")]
		public function get valid():Boolean {
			return validationHelper.valid;
		}
		
		public function isInvalidRequired():Boolean {
			return validationHelper.isInvalidRequired();
		}
		
		public function clearValidation():void {
			errorString = "";
		}
		
		public function set type(value:Class):void {
			validationHelper.type = value;
		}
		
		public function setMetaData(metaData:Object):void {
			validationHelper.setMetaData(metaData);
		}
		
		public function set notNull(value:Boolean):void {
			validationHelper.setMetaDataProp("notNull", value ? true : undefined);
		}
		
		public function set notEmpty(value:Boolean):void {
			validationHelper.setMetaDataProp("notEmpty", value ? true : undefined);
		}
		
		public function set maxLength(value:Object):void {
			validationHelper.setMetaDataProp("maxLength", value != null ? value : undefined);
		}
		
		public function set minLength(value:Object):void {
			validationHelper.setMetaDataProp("minLength", value != null ? value : undefined);
		}
		
		public function set maxValue(value:Object):void {
			validationHelper.setMetaDataProp("maxValue", value != null ? value : undefined);
		}
		
		public function set minValue(value:Object):void {
			validationHelper.setMetaDataProp("minValue", value != null ? value : undefined);
		}

	}
}